from django.core.files.storage import default_storage
from django.db.models import signals
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction

from . import serializers
from .models import TemplateCategory, Template, TemplateLayerGroupElement, TemplateLayerGroup, TemplateElement
from .serializers import (
    TemplateCategorySerializer,
    DetailTemplateCategorySerializer, TemplateSerializer, TemplateImageField
)
from ..CanvasElementManagement.models import CanvasElement, MaskElement, TextElement
from ..CanvasesManagement.models import Canvas
from ..LayerManagement.models import LayerGroupMapping, LayerGroup, handle_element_creation
from ..utils.response_utils import api_response, ResponseCode


def save_base64_image(base64_data, field_type='thumbnail'):
    """
    保存Base64图片
    :param base64_data: Base64图片数据
    :param field_type: 字段类型(thumbnail/preview)
    :return: 存储路径
    """
    if not base64_data:
        return None

    try:
        field = TemplateImageField()
        return field.to_internal_value(base64_data)
    except ValueError as e:
        raise ValueError(f"{field_type}图片处理失败: {str(e)}")


################分类管理################
class TreeTemplateCategoriesView(APIView):
    """获取全部分类（树形结构）"""

    @swagger_auto_schema(
        operation_description="获取模板分类树形结构",
        responses={
            200: DetailTemplateCategorySerializer(many=True),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板分类管理"]
    )
    def get(self, request):
        try:
            # 获取根分类并预取子分类
            queryset = TemplateCategory.objects.filter(parent__isnull=True).prefetch_related('children').order_by(
                'position', 'created_at')
            serializer = DetailTemplateCategorySerializer(queryset, many=True)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class CreateTemplateCategoryView(APIView):
    """创建新分类"""
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        operation_description="创建模板分类",
        request_body=TemplateCategorySerializer,
        responses={
            200: TemplateCategorySerializer,
            400: openapi.Response(description="参数错误")
        },
        tags=["模板分类管理"]
    )
    def post(self, request):
        try:
            with transaction.atomic():
                serializer = TemplateCategorySerializer(data=request.data)
                if serializer.is_valid():
                    serializer.save()
                    return api_response(ResponseCode.SUCCESS, "创建成功", serializer.data)
                return api_response(ResponseCode.BAD_REQUEST, serializer.errors)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class GetCategoryDetailView(APIView):
    """获取分类详情"""

    @swagger_auto_schema(
        operation_description="获取分类详细信息",
        manual_parameters=[
            openapi.Parameter('category_id', openapi.IN_PATH, description="分类ID", type=openapi.TYPE_STRING)
        ],
        responses={
            200: DetailTemplateCategorySerializer,
            404: openapi.Response(description="分类不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板分类管理"]
    )
    def get(self, request, category_id):
        try:
            category = TemplateCategory.objects.get(id=category_id)
            serializer = DetailTemplateCategorySerializer(category)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "分类不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class UpdateTemplateCategoryView(APIView):
    """更新分类信息"""
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        operation_description="更新分类信息",
        manual_parameters=[
            openapi.Parameter('category_id', openapi.IN_PATH, description="分类ID", type=openapi.TYPE_STRING)
        ],
        request_body=TemplateCategorySerializer,
        responses={
            200: TemplateCategorySerializer,
            404: openapi.Response(description="分类不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板分类管理"]
    )
    def put(self, request, category_id):
        try:
            with transaction.atomic():
                category = TemplateCategory.objects.get(id=category_id)
                serializer = TemplateCategorySerializer(category, data=request.data, partial=True)
                if serializer.is_valid():
                    serializer.save()
                    return api_response(ResponseCode.SUCCESS, "更新成功", serializer.data)
                return api_response(ResponseCode.BAD_REQUEST, serializer.errors)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "分类不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class DeleteTemplateCategoryView(APIView):
    """删除分类"""

    @swagger_auto_schema(
        operation_description="删除指定分类",
        manual_parameters=[
            openapi.Parameter('category_id', openapi.IN_PATH, description="分类ID", type=openapi.TYPE_STRING)
        ],
        responses={
            200: "删除成功",
            400: openapi.Response(description="参数错误"),
            404: openapi.Response(description="分类不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板分类管理"]
    )
    def delete(self, request, category_id):
        try:
            with transaction.atomic():
                # 获取分类及预取子分类
                category = TemplateCategory.objects.prefetch_related('children').get(id=category_id)

                # 递归删除所有子分类
                def delete_children(child_category):
                    for child in child_category.children.all():
                        delete_children(child)  # 先删除子级
                        if child.icon_url:
                            default_storage.delete(child.icon_url)
                        child.delete()

                # 执行级联删除
                delete_children(category)

                # 删除当前分类文件
                if category.icon_url:
                    default_storage.delete(category.icon_url)

                category.delete()
                return api_response(ResponseCode.SUCCESS, "删除成功")
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "分类不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


################模版管理################
class TemplateListView(APIView):
    """根据分类查询模板列表（不分页）"""

    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter('category_id', openapi.IN_QUERY, type=openapi.TYPE_STRING)
        ],
        responses={
            200: TemplateSerializer(many=True),
            400: openapi.Response(description="参数错误"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板管理"]
    )
    def get(self, request):
        category_id = request.query_params.get('category_id')
        if not category_id:
            return api_response(ResponseCode.BAD_REQUEST, "必须提供分类ID")

        try:
            templates = Template.objects.filter(category=category_id).prefetch_related('elements')
            serializer = TemplateSerializer(templates, many=True)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class CreateTemplateView(APIView):
    """从画布创建模板"""
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'canvas_id': openapi.Schema(type=openapi.TYPE_STRING),
                'category_id': openapi.Schema(type=openapi.TYPE_STRING),
                'name': openapi.Schema(type=openapi.TYPE_STRING),
                'description': openapi.Schema(type=openapi.TYPE_STRING),
                'thumbnail_base64': openapi.Schema(type=openapi.TYPE_STRING),
                'preview_base64': openapi.Schema(type=openapi.TYPE_STRING)
            },
            required=['canvas_id', 'category_id', 'name']
        ),
        responses={
            200: TemplateSerializer,
            400: openapi.Response(description="参数错误"),
            404: openapi.Response(description="画布不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板管理"]
    )
    def post(self, request):
        try:
            canvas = Canvas.objects.get(id=request.data.get('canvas_id'))

            with transaction.atomic():
                # 处理并保存图片
                thumbnail_url = save_base64_image(
                    request.data.get('thumbnail_base64'),
                    'thumbnail'
                )
                preview_url = save_base64_image(
                    request.data.get('preview_base64'),
                    'preview'
                )

                # 1. 创建模板基础信息
                template = Template.objects.create(
                    category_id=request.data.get('category_id'),
                    name=request.data.get('name', canvas.name),
                    description=request.data.get('description'),
                    canvas_size=canvas.canvas_size,
                    background=canvas.background,
                    thumbnail_url=thumbnail_url,
                    preview_url=preview_url
                )

                # 2. 创建模板元素
                element_map = {}  # {canvas_element_id: template_element}
                for canvas_element in canvas.elements.all():
                    template_element = TemplateElement.objects.create(
                        template=template,
                        origin_element_id=canvas_element.id,
                        type=canvas_element.type,
                        name=canvas_element.name,
                        position=canvas_element.position,
                        size=canvas_element.size,
                        rotation=canvas_element.rotation,
                        opacity=canvas_element.opacity,
                        visible=canvas_element.visible,
                        locked=canvas_element.locked,
                        z_index=canvas_element.z_index,
                        frame_style=canvas_element.frame_style
                    )
                    element_map[canvas_element.id] = template_element

                    # 处理扩展元素数据
                    if canvas_element.type == 'mask':
                        mask = canvas_element.mask_element
                        template_element.content = {
                            'mask_type': mask.mask_type,
                            'mask_content': mask.mask_content
                        }
                        template_element.asset = mask.asset
                        template_element.save()
                    elif canvas_element.type == 'text':
                        text = canvas_element.text_element
                        template_element.content = {
                            'text_content': text.text_content,
                            'font_family': text.font_family,
                            'font_size': text.font_size,
                            'font_weight': text.font_weight,
                            'font_style': text.font_style,
                            'text_align': text.text_align,
                            'line_height': text.line_height,
                            'letter_spacing': text.letter_spacing,
                            'text_color': text.text_color,
                            'text_effects': text.text_effects,
                            'text_transform': text.text_transform,
                            'writing_mode': text.writing_mode
                        }
                        template_element.save()

                # 3. 递归创建图层组结构
                def create_layer_groups(canvas_groups, parent=None, top_group=None):
                    for canvas_group in canvas_groups:
                        # 创建模板图层组
                        template_group = TemplateLayerGroup.objects.create(
                            template=template,
                            name=canvas_group.name,
                            visible=canvas_group.visible,
                            locked=canvas_group.locked,
                            z_index=canvas_group.z_index,
                            parent=parent
                        )

                        # 如果是顶层组且有子组,设置为top_group
                        if parent is None and canvas_group.children.exists():
                            top_group = template_group

                        # 处理组内元素
                        for mapping in canvas_group.elements_mapping.all():
                            canvas_element = mapping.element
                            template_element = element_map.get(canvas_element.id)
                            if template_element:
                                # 创建元素与组的关联
                                TemplateLayerGroupElement.objects.create(
                                    group=template_group,
                                    element=template_element
                                )
                                # 如果存在top_group且不是顶层,设置group_parent_id
                                if top_group and parent is not None:
                                    template_element.group_parent_id = top_group.id
                                    template_element.save()

                        # 递归处理子组
                        create_layer_groups(
                            canvas_group.children.all().order_by('z_index'),
                            parent=template_group,
                            top_group=top_group
                        )

                # 获取并处理顶层图层组
                root_groups = canvas.layer_groups.filter(
                    parent__isnull=True
                ).order_by('z_index')
                create_layer_groups(root_groups)

                return api_response(
                    ResponseCode.SUCCESS,
                    "创建成功",
                    TemplateSerializer(template).data
                )

        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "画布不存在")
        except ValueError as ve:
            return api_response(ResponseCode.BAD_REQUEST, str(ve))
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class UpdateTemplateView(APIView):
    """更新模板（从画布数据）"""
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'canvas_id': openapi.Schema(type=openapi.TYPE_STRING),
                'name': openapi.Schema(type=openapi.TYPE_STRING),
                'description': openapi.Schema(type=openapi.TYPE_STRING),
                'thumbnail_base64': openapi.Schema(type=openapi.TYPE_STRING),
                'preview_base64': openapi.Schema(type=openapi.TYPE_STRING),
            }
        ),
        responses={
            200: TemplateSerializer,
            400: openapi.Response(description="参数错误"),
            404: openapi.Response(description="模板或画布不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板管理"]
    )
    def put(self, request, template_id):
        try:
            template = Template.objects.get(id=template_id)
            canvas = Canvas.objects.get(id=request.data.get('canvas_id'))

            with transaction.atomic():
                # 1. 更新模板基本信息
                if 'name' in request.data:
                    template.name = request.data['name']
                if 'description' in request.data:
                    template.description = request.data['description']
                # 处理并保存图片
                if 'thumbnail_base64' in request.data:
                    if template.thumbnail_url:
                        default_storage.delete(template.thumbnail_url)
                    template.thumbnail_url = save_base64_image(
                        request.data['thumbnail_base64'],
                        'thumbnail'
                    )

                if 'preview_base64' in request.data:
                    if template.preview_url:
                        default_storage.delete(template.preview_url)
                    template.preview_url = save_base64_image(
                        request.data['preview_base64'],
                        'preview'
                    )

                template.canvas_size = canvas.canvas_size
                template.background = canvas.background
                template.save()

                # 2. 清除原有数据
                template.elements.all().delete()
                template.template_layer_groups.all().delete()

                # 3. 从画布创建新的元素
                element_map = {}  # {canvas_element_id: template_element}
                for canvas_element in canvas.elements.all():
                    template_element = TemplateElement.objects.create(
                        template=template,
                        origin_element_id=canvas_element.id,
                        type=canvas_element.type,
                        name=canvas_element.name,
                        position=canvas_element.position,
                        size=canvas_element.size,
                        rotation=canvas_element.rotation,
                        opacity=canvas_element.opacity,
                        visible=canvas_element.visible,
                        locked=canvas_element.locked,
                        z_index=canvas_element.z_index,
                        frame_style=canvas_element.frame_style
                    )
                    element_map[canvas_element.id] = template_element

                    # 处理扩展数据
                    if canvas_element.type == 'mask':
                        mask = canvas_element.mask_element
                        template_element.content = {
                            'mask_type': mask.mask_type,
                            'mask_content': mask.mask_content
                        }
                        template_element.asset = mask.asset
                        template_element.save()
                    elif canvas_element.type == 'text':
                        text = canvas_element.text_element
                        template_element.content = {
                            'text_content': text.text_content,
                            'font_family': text.font_family,
                            'font_size': text.font_size,
                            'font_weight': text.font_weight,
                            'font_style': text.font_style,
                            'text_align': text.text_align,
                            'line_height': text.line_height,
                            'letter_spacing': text.letter_spacing,
                            'text_color': text.text_color,
                            'text_effects': text.text_effects,
                            'text_transform': text.text_transform,
                            'writing_mode': text.writing_mode
                        }
                        template_element.save()

                # 4. 递归创建新的图层组结构
                def create_layer_groups(canvas_groups, parent=None, top_group=None):
                    for canvas_group in canvas_groups:
                        # 创建模板图层组
                        template_group = TemplateLayerGroup.objects.create(
                            template=template,
                            name=canvas_group.name,
                            visible=canvas_group.visible,
                            locked=canvas_group.locked,
                            z_index=canvas_group.z_index,
                            parent=parent
                        )

                        # 如果是顶层组且有子组,设置为top_group
                        if parent is None and canvas_group.children.exists():
                            top_group = template_group

                        # 处理组内元素
                        for mapping in canvas_group.elements_mapping.all():
                            canvas_element = mapping.element
                            template_element = element_map.get(canvas_element.id)
                            if template_element:
                                # 创建元素与组的关联
                                TemplateLayerGroupElement.objects.create(
                                    group=template_group,
                                    element=template_element
                                )
                                # 如果存在top_group且不是顶层,设置group_parent_id
                                if top_group and parent is not None:
                                    template_element.group_parent_id = top_group.id
                                    template_element.save()

                        # 递归处理子组
                        create_layer_groups(
                            canvas_group.children.all().order_by('z_index'),
                            parent=template_group,
                            top_group=top_group
                        )

                # 获取处理顶层图层组
                root_groups = canvas.layer_groups.filter(
                    parent__isnull=True
                ).order_by('z_index')
                create_layer_groups(root_groups)

                return api_response(
                    ResponseCode.SUCCESS,
                    "更新成功",
                    TemplateSerializer(template).data
                )

        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "模板或画布不存在")
        except ValueError as ve:
            return api_response(ResponseCode.BAD_REQUEST, str(ve))
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class BatchDeleteTemplatesView(APIView):
    """批量删除模板"""

    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter('ids', openapi.IN_QUERY, type=openapi.TYPE_ARRAY,
                              items=openapi.Items(type=openapi.TYPE_STRING))
        ],
        responses={
            200: "删除成功",
            400: openapi.Response(description="参数错误"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["模板管理"]
    )
    def delete(self, request):
        try:
            template_ids = request.query_params.get('ids', '').split(',')
            if not template_ids:
                return api_response(ResponseCode.BAD_REQUEST, "必须提供模板ID列表")

            with transaction.atomic():
                templates = Template.objects.filter(id__in=template_ids)
                # 删除关联文件
                for template in templates:
                    if template.thumbnail_url:
                        default_storage.delete(template.thumbnail_url)
                    if template.preview_url:
                        default_storage.delete(template.preview_url)
                    template.delete()
                return api_response(ResponseCode.SUCCESS, "删除成功")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class UseTemplateView(APIView):
    """使用模板创建画布"""

    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'project_id': openapi.Schema(type=openapi.TYPE_STRING),
                'replace_canvas_id': openapi.Schema(type=openapi.TYPE_STRING)
            }
        ),
        tags=["模板管理"]
    )
    def post(self, request, template_id):
        try:
            template = Template.objects.get(id=template_id)
            project_id = request.data.get('project_id')
            replace_canvas_id = request.data.get('replace_canvas_id')

            with transaction.atomic():
                # 创建或获取画布
                if replace_canvas_id:
                    canvas = Canvas.objects.get(id=replace_canvas_id)
                    # 清除现有元素和图层组
                    canvas.elements.all().delete()
                    canvas.layer_groups.all().delete()
                else:
                    canvas = Canvas.objects.create(
                        project_id=project_id,
                        name=template.name,
                        canvas_size=template.canvas_size,
                        background=template.background
                    )

                # ID映射
                element_map = {}  # {origin_element_id: canvas_element}
                group_map = {}  # {template_group_id: layer_group}

                # 暂时禁用自动创建图层组的信号
                signals.post_save.disconnect(handle_element_creation, sender=CanvasElement)

                try:
                    # 1. 创建所有元素
                    for template_element in template.elements.all():
                        # 创建基础画布元素
                        canvas_element = CanvasElement.objects.create(
                            canvas=canvas,
                            type=template_element.type,
                            name=template_element.name,
                            position=template_element.position,
                            size=template_element.size,
                            rotation=template_element.rotation,
                            opacity=template_element.opacity,
                            visible=template_element.visible,
                            locked=template_element.locked,
                            z_index=template_element.z_index,
                            frame_style=template_element.frame_style,
                            group_parent_id=None  # 临时置空
                        )

                        # 存储映射关系
                        element_map[template_element.origin_element_id] = canvas_element

                        # 创建扩展元素数据
                        if template_element.type == 'mask' or (
                                template_element.type == 'group' and template_element.asset):
                            MaskElement.objects.create(
                                element=canvas_element,
                                mask_type=template_element.content.get('mask_type', 'image'),
                                mask_content=template_element.content.get('mask_content', {}),
                                asset=template_element.asset
                            )
                        elif template_element.type == 'text' or (
                                template_element.type == 'group' and template_element.content.get('text_content')):
                            content = template_element.content
                            TextElement.objects.create(
                                element=canvas_element,
                                text_content=content.get('text_content', '默认文本'),
                                font_family=content.get('font_family', 'Arial'),
                                font_size=content.get('font_size', 12.0),
                                font_weight=content.get('font_weight', 'normal'),
                                font_style=content.get('font_style', 'normal'),
                                text_align=content.get('text_align', 'left'),
                                line_height=content.get('line_height', 1.2),
                                letter_spacing=content.get('letter_spacing', 0.0),
                                text_color=content.get('text_color', '#000000'),
                                text_effects=content.get('text_effects', {}),
                                text_transform=content.get('text_transform', {}),
                                writing_mode=content.get('writing_mode', 'horizontal')
                            )

                    # 2. 递归创建图层组结构
                    def create_layer_groups(template_groups, parent=None, top_group=None):
                        for group in template_groups:
                            # 创建图层组
                            layer_group = LayerGroup.objects.create(
                                canvas=canvas,
                                name=group.name,
                                visible=group.visible,
                                locked=group.locked,
                                z_index=group.z_index,
                                parent=parent
                            )
                            group_map[group.id] = layer_group

                            # 如果是顶层组且有子组,设置为 top_group
                            if parent is None and group.children.exists():
                                top_group = layer_group

                            # 处理元素关联
                            for mapping in group.element_group_mapping.all():
                                canvas_element = element_map.get(mapping.element.origin_element_id)
                                if canvas_element:
                                    LayerGroupMapping.objects.create(
                                        group=layer_group,
                                        element=canvas_element
                                    )
                                    # 如果存在 top_group 且不是顶层组,设置 group_parent_id
                                    if top_group and parent is not None:
                                        canvas_element.group_parent_id = top_group.id
                                        canvas_element.save(update_fields=['group_parent_id'])

                            # 递归处理子组,传递 top_group
                            create_layer_groups(group.children.all(), parent=layer_group, top_group=top_group)

                    # 创建顶层图层组
                    top_groups = template.template_layer_groups.filter(parent__isnull=True).order_by('z_index')
                    create_layer_groups(top_groups)

                finally:
                    # 恢复信号连接
                    signals.post_save.connect(handle_element_creation, sender=CanvasElement)

                return api_response(ResponseCode.SUCCESS, "操作成功", {'canvas_id': canvas.id})

        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "模板或画布不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))
